<?php

namespace app\api\controller;

use app\admin\model\factor\CarbonFactor as CarbonFactorModel;
use app\admin\model\Node as NodeModel;
use app\admin\model\NodeDetail as NodeDetailModel;
use app\admin\model\Product as ProductModel;
use app\admin\model\template\Order as OrderModel;
use app\common\controller\Api;
use fast\Random;
use think\Db;
use think\Exception;
use think\exception\DbException;

/**
 * 节点接口
 */
class Node extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = '*';

    protected $model = null;
    protected $limit_node_per_rank = 270;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new NodeModel();
    }

    /**
     * 查询层级的节点数
     */
    protected function count_node_per_rank($node, $rank)
    {
        if ($rank == 1) {
            $current_nodes = $this->model->where('product_id', $node->product_id)
                                        ->where('rank', 1)
                                        ->whereOr(function($query) {
                                            $query->where('rank', 2);
                                            $query->where('origin_path', '-');
                                        })
                                        ->count();
        } else {
            $current_nodes = $this->model->where('product_id', $node->product_id)->where('template_mark', $node->template_mark)->count();
        }

        return $current_nodes;
    }

    /**
     * 添加父级节点
     */
    public function create_parent()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'rank|节点层级' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能添加');
        }

        if ($node->level == 1) {
            $this->error('该节点为最父级节点，不能添加');
        }

        $current_nodes = $this->count_node_per_rank($node, $row['rank']);

        if ($current_nodes == $this->limit_node_per_rank) {
            $this->error('当前层级节点总数已达上限');
        }

        Db::startTrans();
        try {
            // 添加父级节点
            $this->model->pid = $node->pid;
            $this->model->product_id = $node->product_id;
            $this->model->level = $node->level;
            $this->model->path = $node->path;
            $this->model->user_id = $node->user_id;
            if ($row['rank'] != 1) {
                $this->model->from_template = $node->from_template;
                $this->model->rank = $node->rank;
                $this->model->template_mark = $node->template_mark;
            }
            $this->model->save();

            // 修改自身节点
            $node->pid = $this->model->id;
            $node->level = $node->level + 1;
            $node->path = $node->path . $this->model->id . '-';
            $node->save();

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error('添加父级节点失败: ' . $e->getMessage());
        }

        $this->success('添加父级节点成功', $this->model);
    }

    /**
     * 添加同级节点
     */
    public function create_same()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'rank|节点层级' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能添加');
        }

        if ($node->level == 1) {
            $this->error('该节点为最父级节点，不能添加');
        }

        $current_nodes = $this->count_node_per_rank($node, $row['rank']);

        if ($current_nodes == $this->limit_node_per_rank) {
            $this->error('当前层级节点总数已达上限');
        }

        try {
            // 添加同级节点
            $this->model->pid = $node->pid;
            $this->model->product_id = $node->product_id;
            $this->model->level = $node->level;
            $this->model->path = $node->path;
            $this->model->user_id = $node->user_id;
            if ($row['rank'] != 1) {
                $this->model->from_template = $node->from_template;
                $this->model->rank = $node->rank;
                $this->model->template_mark = $node->template_mark;
            }
            $this->model->save();

        } catch (Exception $e) {
            $this->error('添加同级节点失败: ' . $e->getMessage());
        }

        $this->success('添加同级节点成功', $this->model);
    }

    /**
     * 添加子级节点
     */
    public function create_children()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'rank|节点层级' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能添加');
        }

        if ($node->is_factor == 1) {
            $this->error('该节点是引用碳排放因子&数据库节点，不能添加');
        }

        $current_nodes = $this->count_node_per_rank($node, $row['rank']);

        if ($current_nodes == $this->limit_node_per_rank) {
            $this->error('当前层级节点总数已达上限');
        }

        try {
            // 添加子级节点
            $this->model->pid = $node->id;
            $this->model->product_id = $node->product_id;
            $this->model->level = $node->level + 1;
            $this->model->path = $node->path . $node->id . '-';
            $this->model->user_id = $node->user_id;
            if ($row['rank'] != 1) {
                $this->model->from_template = $node->from_template;
                $this->model->rank = $node->rank;
                $this->model->template_mark = $node->template_mark;
            }
            $this->model->save();

        } catch (Exception $e) {
            $this->error('添加子级节点失败: ' . $e->getMessage());
        }

        $this->success('添加子级节点成功', $this->model);
    }

    /**
     * 输入节点信息
     */
    public function edit()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'type|类型' => 'require|in:name,amount,quality',
            'name|名称' => 'requireIf:type,name',
            'amount|数量' => 'requireIf:type,amount|number|>:0|<:2147483647',
            'quality|质量' => 'requireIf:type,quality|>:0|regex:/^\d{1,8}(\.\d{1,4})?$/',
            'node_id|节点ID' => 'number|require'
        ];
        $message = [
            'quality.regex' => '质量请填写8位及以内的整数, 4位及以内的小数',
        ];
        $validate = $this->validate($row, $rule, $message);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能编辑');
        }

        try {
            if ($row['type'] == 'name') {
                $node->name = $row['name'];
            } elseif ($row['type'] == 'amount') {
                $node->produce_amount = $row['amount'];
            } else {
                $node->produce_quality = $row['quality'];
            }

            $node->save();
        } catch (Exception $e) {
            $this->error('保存失败: ' . $e->getMessage());
        }

        $this->success('保存成功');
    }

    /**
     * 输入能源/输出废弃
     */
    public function entry()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'type|类型' => 'require|in:energy,waste',
            'node_id|节点ID' => 'number|require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能输入');
        }

        try {
            if ($row['type'] == 'energy') {
                $node_detail = NodeDetailModel::create(['node_id' => $row['node_id'], 'user_id' => $node->user_id, 'product_id' => $node->product_id]);
            } else {
                $node_detail = NodeDetailModel::create(['node_id' => $row['node_id'], 'user_id' => $node->user_id, 'product_id' => $node->product_id, 'type' => 1]);
            }
        } catch (Exception $e) {
            $this->error('操作失败: ' . $e->getMessage());
        }

        $this->success('操作成功', ['node_detail_id' => $node_detail->id]);
    }

    /**
     * 输入能源/废弃物信息
     */
    public function edit_io()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'type|类型' => 'require|in:io_category_id,io_type_id,io_value',
            'io_type_id|类型ID' => 'requireIf:type,io_type_id|number',
            'io_category_id|类别ID' => 'requireIf:type,io_category_id|number',
            'io_value|输入/输出量' => 'requireIf:type,io_value|>:0|regex:/^\d{1,8}(\.\d{1,4})?$/',
            'node_detail_id|节点详情ID' => 'number|require'
        ];
        $message = [
            'io_value.regex' => '输入/输出量请填写8位及以内的整数, 4位及以内的小数',
        ];
        $validate = $this->validate($row, $rule, $message);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node_detail = NodeDetailModel::get($row['node_detail_id']);

        if (!$node_detail) {
            $this->error('节点详情记录不存在');
        }

        if ($node_detail->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能输入');
        }

        Db::startTrans();
        try {
            if ($row['type'] == 'io_type_id') {
                if ($node_detail->io_type_id != $row['io_type_id']) {
                    $node_detail->io_category_id = 0;
                }
                $node_detail->io_type_id = $row['io_type_id'];

                //记录用户使用的类型
                $record = Db::name('user_io_category')
                    ->where('user_id', $node_detail->user_id)
                    ->where('product_id', $node_detail->product_id)
                    ->where('io_category_id', $row['io_type_id'])
                    ->find();
                if (!$record) {
                    Db::name('user_io_category')->insert([
                        'user_id' => $node_detail->user_id,
                        'product_id' => $node_detail->product_id,
                        'io_category_id' => $row['io_type_id'],
                        'type' => 0,
                        'createtime' => time(),
                        'updatetime' => time()
                    ]);
                }
            } elseif ($row['type'] == 'io_category_id') {
                $node_detail->io_category_id = $row['io_category_id'];

                //记录用户使用的类别
                $record = Db::name('user_io_category')
                    ->where('user_id', $node_detail->user_id)
                    ->where('product_id', $node_detail->product_id)
                    ->where('io_category_id', $row['io_category_id'])
                    ->find();
                if (!$record) {
                    Db::name('user_io_category')->insert([
                        'user_id' => $node_detail->user_id,
                        'product_id' => $node_detail->product_id,
                        'io_category_id' => $row['io_category_id'],
                        'type' => 1,
                        'createtime' => time(),
                        'updatetime' => time()
                    ]);
                }
            } else {
                $node_detail->io_value = $row['io_value'];
            }

            $node_detail->save();

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error('保存失败: ' . $e->getMessage());
        }

        $this->success('保存成功');
    }

    /**
     * 删除输入能源/输出废弃记录
     */
    public function delete_io()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_detail_id|节点详情ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node_detail = NodeDetailModel::get($row['node_detail_id']);

        if (!$node_detail) {
            $this->error('节点详情记录不存在');
        }

        if ($node_detail->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能删除');
        }

        try {
            // 删除
            $node_detail->delete();

        } catch (Exception $e) {
            $this->error('删除失败: ' . $e->getMessage());
        }

        $this->success('删除成功');
    }

    /**
     * 删除节点
     */
    public function delete()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能删除');
        }

        if ($node->level == 1) {
            $this->error('该节点为最父级节点，不能删除');
        }

        Db::startTrans();
        try {
            
            $ids = $node->children_ids;
            array_push($ids, $node->id);
            // 删除节点信息
            $this->model->whereIn('id', $ids)->delete();
            // 删除节点下的输入输出能源信息
            NodeDetailModel::whereIn('node_id', $ids)->delete();

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error('删除节点失败: ' . $e->getMessage());
        }

        $this->success('删除节点成功', ['pid' => $node->pid]);
    }

    /**
     * 选择类型
     */
    public function select_io_type()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_detail_id|节点详情ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node_detail = NodeDetailModel::get($row['node_detail_id']);

        if (!$node_detail) {
            $this->error('节点详情记录不存在');
        }

        //全部类型
        $list = Db::name('io_category')->field('id,name,unit')->where('pid', 0)->where('type', $node_detail->type)->select();

        //使用过的类型
        $usedList = Db::name('user_io_category')
            ->alias('u')
            ->join('io_category i', 'u.io_category_id = i.id')
            ->field('i.id,i.name,i.unit')
            ->where('u.type', 0)
            ->where('u.user_id', $node_detail->user_id)
            ->where('u.product_id', $node_detail->product_id)
            ->where('i.type', $node_detail->type)
            ->select();

        $this->success('查询成功', ['used' => $usedList, 'all' => $list]);
    }

    /**
     * 选择类别
     */
    public function select_io_category()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_detail_id|节点详情ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node_detail = NodeDetailModel::get($row['node_detail_id']);

        if (!$node_detail) {
            $this->error('节点详情记录不存在');
        }

        if ($node_detail->io_type_id == 0) {
            // 全部类别
            $list = Db::name('io_category')->field('id,name,unit')->where('pid', '<>', 0)->where('type', $node_detail->type)->select();
            // 使用过的类别
            $usedList = Db::name('user_io_category')
                ->alias('u')
                ->join('io_category i', 'u.io_category_id = i.id')
                ->field('i.id,i.name,i.unit')
                ->where('u.type', 1)
                ->where('i.type', $node_detail->type)
                ->select();
        } else {
            // 指定类别
            $list = Db::name('io_category')->field('id,name,unit')->where('pid', $node_detail->io_type_id)->where('type', $node_detail->type)->select();
            // 使用过的指定类别
            $usedList = Db::name('user_io_category')
                ->alias('u')
                ->join('io_category i', 'u.io_category_id = i.id')
                ->field('i.id,i.name,i.unit')
                ->where('u.type', 1)
                ->where('u.user_id', $node_detail->user_id)
                ->where('u.product_id', $node_detail->product_id)
                ->where('i.type', $node_detail->type)
                ->where('i.pid', $node_detail->io_type_id)
                ->select();
        }

        $this->success('查询成功', ['used' => $usedList, 'all' => $list]);
    }


    /**
     * 节点核算
     */
    public function calculate()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能核算');
        }

        if ($node->is_factor == 1) {
            $this->error('该节点是引用碳排放因子&数据库节点，不能核算');
        }

        // 非因子节点
        $ids = $node->product_children_ids;
        array_push($ids, $row['node_id']);
        $data = NodeDetailModel::whereIn('node_id', $ids)->select();
        $node_data = NodeModel::whereIn('id', $ids)->select();
        // 因子节点
        $factor_ids = $node->factor_children_ids;
        $factor_data = NodeModel::whereIn('id', $factor_ids)->select();

        $info = []; //错误信息

        //检查节点信息是否完善
        foreach ($data as $v) {
            if ($v->io_type_id == 0 ||
                $v->io_category_id == 0 ||
                !$v->io_value) {
                $info[$v->node->id] = $v->node->name;
                continue;
            }
        }
        //检查生产质量和生产数量和节点名称是否填写完整
        foreach ($node_data as $v) {
            if (!$v->produce_amount || !$v->produce_quality || !$v->name) {
                $info[$v->id] = $v->name;
                continue;
            }
        }
        

        $factor_arr1 = [];//需购买的因子
        $factor_arr2 = [];//我创建的因子
        $previous = [];//用于储存每一个因子id
        foreach ($factor_data as $k => $v) {
            if ($v->factor_id == 0 || !$v->factor_quotes) {
                $info[$v->id] = $v->name;
                continue;
            }
            if (!in_array($v->factor_id, $previous)) {
                if ($v->factor_user != $this->auth->id) {
                    $factor_arr1[$k]['factor_id'] = $v->factor_id;
                    $factor_arr1[$k]['name'] = $v->name;
                    $factor_arr1[$k]['sn'] = $v->factor_sn;
                    $factor_arr1[$k]['factor'] = $v->factor;
                    $factor_arr1[$k]['check'] = false;
                } else {
                    $factor_arr2[$k]['factor_id'] = $v->factor_id;
                    $factor_arr2[$k]['name'] = $v->name;
                    $factor_arr2[$k]['sn'] = $v->factor_sn;
                    $factor_arr2[$k]['factor'] = $v->factor;
                    $factor_arr2[$k]['check'] = false;
                }
            }
            $previous[] = $v->factor_id;
        }

        if ($info) {
            $this->error('无法核算', $info);
        }

        $this->success('ok', [
            'node' => $node, 
            'total_node' => count($ids) + count($factor_ids), 
            'factor1' => $factor_arr1, 
            'total_factor1' => count($factor_arr1),
            'factor2' => $factor_arr2, 
            'total_factor2' => count($factor_arr2),
            'total_type' => count($data) + count($factor_ids)
        ]);

    }

    /**
     * 引用碳排放因子&数据库
     */
    public function quote_factor()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'rank|节点层级' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能引用');
        }

        if ($node->is_factor == 1) {
            $this->error('该节点是引用碳排放因子&数据库节点，不能引用');
        }

        $current_nodes = $this->count_node_per_rank($node, $row['rank']);

        if ($current_nodes == $this->limit_node_per_rank) {
            $this->error('当前层级节点总数已达上限');
        }

        try {
            // 添加子级节点
            $this->model->pid = $node->id;
            $this->model->product_id = $node->product_id;
            $this->model->level = $node->level + 1;
            $this->model->path = $node->path . $node->id . '-';
            $this->model->user_id = $node->user_id;
            $this->model->is_factor = 1;
            if ($row['rank'] != 1) {
                $this->model->from_template = $node->from_template;
                $this->model->rank = $node->rank;
                $this->model->template_mark = $node->template_mark;
            }
            $this->model->save();

        } catch (Exception $e) {
            $this->error('引用碳排放因子&数据库失败: ' . $e->getMessage());
        }

        $this->success('引用碳排放因子&数据库成功', $this->model);
    }

    /**
     * 选择碳排放因子&数据库
     */
    public function select_factor()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'factor_id|因子ID' => 'number|require',
            'factor_name|因子名称' => 'require',
            'factor_type|因子类型' => 'require|in:1,2',//1产品2原材料
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能选择');
        }

        if ($node->is_factor != 1) {
            $this->error('该节点不是引用碳排放因子&数据库节点，不能选择');
        }

        try {
            $node->factor_id = $row['factor_id'];
            $node->name = $row['factor_name'];
            $node->node_type = 2;
            $node->save();
        } catch (Exception $e) {
            $this->error('选择碳排放因子&数据库失败: ' . $e->getMessage());
        }

        $this->success('选择碳排放因子&数据库成功');
    }

    /**
     * 保存碳排放因子&数据库节点引用量
     */
    public function save_factor_quotes()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'factor_quotes|引用量' => 'require|>:0|regex:/^\d{1,8}(\.\d{1,4})?$/',
        ];
        $message = [
            'factor_quotes.regex' => '质量请填写8位及以内的整数, 4位及以内的小数',
        ];
        $validate = $this->validate($row, $rule, $message);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能操作');
        }

        if ($node->is_factor != 1) {
            $this->error('该节点不是引用碳排放因子&数据库节点，不能操作');
        }

        if ($node->factor_id == 0) {
            $this->error('未选择碳排放因子&数据库，不能操作');
        }

        try {
            $node->factor_quotes = $row['factor_quotes'];
            $node->save();
        } catch (Exception $e) {
            $this->error('保存失败: ' . $e->getMessage());
        }

        $this->success('保存成功');
    }

    /**
     * 查看节点信息
     */
    public function detail()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->is_factor == 0) {
            // 输入
            $input = NodeDetailModel::where('node_id', $node->id)->where('type', 0)->select();
            // 输出
            $output = NodeDetailModel::where('node_id', $node->id)->where('type', 1)->select();

            $count = $this->model->where('product_id', $node->product_id)->where('template_mark', $node->template_mark)->count();

            $this->success('查询成功', ['is_factor' => 0, 'node' => $node, 'input' => $input, 'output' => $output, 'total_children_node' => count($node->children_ids), 'count' => $count]);

        } else {
            $factor_detail = CarbonFactorModel::where('id', $node->factor_id)->find();
            $node->factor_detail = $factor_detail;
            $node->company_name = $factor_detail['company_name'] ?? '';
            $this->success('查询成功', ['is_factor' => 1, 'node' => $node, 'input' => [], 'output' => []]);
        }
    }

    /**
     * 查看全部节点信息
     */
    public function all_detail()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        $ids = $node->children_ids;
        array_push($ids, $node->id);
        $data = NodeModel::field('id,name,produce_amount,is_factor,factor_quotes')->whereIn('id', $ids)->paginate();

        foreach ($data as $v) {
            if ($v->is_factor != 1) {
                $v->io_count = NodeDetailModel::where('node_id', $v->id)->count();
            }
        }

        $this->success('查询成功', $data);

    }

    /**
     * 确认核算内容
     */
    public function check_calculate_info()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能确认');
        }

        $ids = $node->product_children_ids;
        array_push($ids, $row['node_id']);
        $data = NodeDetailModel::whereIn('node_id', $ids)->select();
        $factor_ids = $node->factor_children_ids;
        $total_type = count($data) + count($factor_ids);

        // 因子信息
        $factor_id = $this->request->post('factor_id', '');
        $factor_id = explode(',', $factor_id);
        $factor = Db::name('carbon_factor')->field('id,sn,name,price')->whereIn('id', $factor_id)->select();

        $total_energy = $this->get_service_energy($total_type);
        if ($factor) {
            foreach ($factor as $v) {
                $total_energy += $v['price'];
            }
        }

        $this->success('', [
            'user_name' => $this->auth->nickname,
            'avatar' => $this->auth->avatar,
            'factor' => $factor,
            'total_energy' => $total_energy,
            'calculate_service_energy' => $this->get_service_energy($total_type)
        ]);
    }

    protected function get_service_energy($num)
    {
        if ($num >= 0 && $num <= 50) {
            return 500;
        } elseif ($num >= 51 && $num <= 100) {
            return 1000;
        } elseif ($num >= 101 && $num <= 200) {
            return 2000;
        } elseif ($num >= 201 && $num <= 500) {
            return 3000;
        } elseif ($num >= 501 && $num <= 1000) {
            return 4000;
        } else {
            return 5000;
        }
    }

    /**
     * 支付订单
     */
    public function pay()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'order_sn|订单编号' => 'require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $order = OrderModel::where('order_sn', $row['order_sn'])->where('type', 2)->find();

        if (!$order) {
            $this->error('订单不存在');
        }

        if ($order['user_id'] != $this->auth->id) {
            $this->error('只能支付自己的订单');
        }

        if ($order['pay_state'] == 1) {
            $this->error('订单已支付');
        }

        if ($order['pay_state'] == 2) {
            $this->error('订单已取消');
        }

        // 查询公司能量是否充足
        $qd = Db::connect(config('database')['qd']);

        $company = $qd->table('fa_department')->where('id', $order['company_id'])->find();

        if (!$company) {
            $this->error('公司不存在，无法支付');
        }

        if ($company['score'] < $order['price']) {
            $this->error('公司能量不足');
        }

        Db::startTrans();
        $qd->startTrans();

        try {
            // 能量扣除
            $before = $company['score'];
            $after = $company['score'] - $order['price'];
            $qd->table('fa_department')->where('id', $order['company_id'])->update([
                'score' => $after
            ]);

            // 记录日志
            $qd->table('fa_department_score_log')->insert([
                'user_id' => $this->auth->id,
                'company_id' => $this->auth->company_id,
                'score' => $order['price'],
                'before' => $before,
                'after' => $after,
                'source' => '碳足迹',
                'memo' => '支付碳核算订单',
                'createtime' => time()
            ]);

            $order->pay_state = 1;
            $order->paytime = time();
            $order->save();

            // 作者增加收益
            $factor = Db::name('order_factor')
                ->alias('f')
                ->join('user u', 'f.from_user = u.id')
                ->field('u.qd_user_id,u.company_id,f.price,f.factor_id')
                ->where('f.order_id', $order->id)
                ->select();

            $template = Db::name('order_template')
                ->alias('t')
                ->join('user u', 't.from_user = u.id')
                ->field('u.qd_user_id,u.company_id,t.commission')
                ->where('t.order_id', $order->id)
                ->select();

            foreach ($factor as $v) {
                // 增加收益,即贡献值
                $company = $qd->table('fa_department')->where('id', $v['company_id'])->find();
                $before = $company['money'];
                $after = $company['money'] + $v['price'];
                $qd->table('fa_department')->where('id', $v['company_id'])->update([
                    'money' => $after
                ]);

                // 记录日志
                $qd->table('fa_department_money_log')->insert([
                    'user_id' => $v['qd_user_id'],
                    'company_id' => $v['company_id'],
                    'money' => $v['price'],
                    'before' => $before,
                    'after' => $after,
                    'source' => '碳足迹',
                    'memo' => '因子库引用收益',
                    'createtime' => time()
                ]);

                // 增加销量
                Db::name('carbon_factor')->where('id', $v['factor_id'])->setInc('sales');
            }

            foreach ($template as $v) {
                // 增加收益,即贡献值
                $company = $qd->table('fa_department')->where('id', $v['company_id'])->find();
                $before = $company['money'];
                $after = $company['money'] + $v['commission'];
                $qd->table('fa_department')->where('id', $v['company_id'])->update([
                    'money' => $after
                ]);

                // 记录日志
                $qd->table('fa_department_money_log')->insert([
                    'user_id' => $v['qd_user_id'],
                    'company_id' => $v['company_id'],
                    'money' => $v['commission'],
                    'before' => $before,
                    'after' => $after,
                    'source' => '碳足迹',
                    'memo' => '模板引用收益',
                    'createtime' => time()
                ]);
            }

            $qd->commit();
            Db::commit();
        } catch (Exception $e) {
            $qd->rollback();
            Db::rollback();
            $this->error("支付失败: " . $e->getMessage());
        }

        $this->success('支付成功');

    }

    /**
     * 核算成功支付的订单(定时任务)
     */
    public function auto_calculate_bak()
    {
        $orders = OrderModel::where('type', 2)
            ->where('pay_state', 1)
            ->where('calculate_status', 0)
            ->select();

        foreach ($orders as $v) {

            $node = NodeModel::get($v->node_id);

            // 非因子节点
            $ids = $node->product_children_ids;
            array_push($ids, $node->id);
            $data = NodeDetailModel::whereIn('node_id', $ids)->select();

            // 购买的因子
            $buy_factor_ids = array_column($v->factors, 'id');
            // 因子节点
            $node_ids_of_factors = $node->factor_children_ids;
            // 获取购买的因子节点
            $factor_data = NodeModel::whereIn('id', $node_ids_of_factors)->whereIn('factor_id', $buy_factor_ids)->select();

            // 生成快照
            $children_node_ids = $node->children_ids;
            array_push($children_node_ids, $node->id);
            $tree = NodeModel::field('id,pid,name as topic,is_factor')->whereIn('id', $children_node_ids)->select()->toArray();
            $snapshot = $this->buildTree($tree, $node->pid);

            $nodes = NodeModel::with(['factor', 'template'])
                ->field('id,pid,name,node_type,factor_id,from_template')
                ->whereIn('id', $children_node_ids)
                ->select();
            foreach ($nodes as $n) {
                $n->factor_name = $n->factor->name;
                $n->factor_value = $n->factor->carbon_factor_result_kg;
                $n->category_name = $n->template->category_name;
                $n->group_name = $n->template->group_name;
            }

            $sum_by_amount = 0;
            $sum_by_amount_ycl = 0; //因子类型为原材料
            foreach ($data as $v1) {
                $sum_by_amount += round((intval($v1->factor * 100000) * intval($v1->io_value * 10000)) / intval($v1->node->produce_amount * 10000 * 100000), 6);
            }

            foreach ($factor_data as $v2) {
                $sum_by_amount += round($v2->factor_quotes * $v2->factor, 6);
                if ($v2->node_type == 2) {
                    $sum_by_amount_ycl += round($v2->factor_quotes * $v2->factor, 6);
                }
            }

            $sum_by_amount = round($sum_by_amount, 5);//总因子,每个
            $sum_by_amount_ycl = round($sum_by_amount_ycl, 5);//原材料因子,每个
            $sum_by_amount_cp = bcsub($sum_by_amount, $sum_by_amount_ycl, 5);//产品因子,每个

            $sum_by_quality = round($sum_by_amount * $node->produce_amount / $node->produce_quality, 5);//总因子,每kg
            $ycl_kg = round($sum_by_amount_ycl * $node->produce_amount / $node->produce_quality, 5);//原材料因子,每kg
            $cp_kg = bcsub($sum_by_quality, $ycl_kg, 5);//产品因子,每kg

            $extra = [
                'ycl' => (float)$sum_by_amount_ycl,
                'cp' => (float)$sum_by_amount_cp,
                'ycl_kg' => (float)$ycl_kg,
                'cp_kg' => (float)$cp_kg,
            ];

            $carbon_result = round($sum_by_amount * $node->produce_amount, 2);//总排放量

            $result = Db::name('carbon_factor')->insert([
                'sn' => Random::alnum(14),
                'name' => $node->level == 1 ? $node->product->name : $node->product->name . '-' . $node->name,
                'order_id' => $v->id,
                'user_id' => $node->user_id,
                'carbon_result' => $carbon_result,
                'carbon_factor_result' => $sum_by_amount,
                'carbon_factor_result_kg' => $sum_by_quality,
                'snapshot' => json_encode($snapshot, JSON_UNESCAPED_UNICODE),
                'createtime' => time(),
                'updatetime' => time(),
                'extra' => json_encode($extra, JSON_UNESCAPED_UNICODE),
                'nodes' => json_encode($nodes, 256)
            ]);

            // 修改订单核算状态
            $v->calculate_status = 1;
            $v->save();
        }

        echo '执行成功';
    }

    /**
     * 核算时核算各个节点
     */
    public function auto_calculate()
    {
        $orders = OrderModel::where('type', 2)
            ->where('pay_state', 1)
            ->where('calculate_status', 0)
            ->select();

        foreach ($orders as $order) {

            $node = NodeModel::get($order->node_id);
        
            // 产品节点
            $ids = $node->product_children_ids;
            array_push($ids, $node->id);
            $product_node = NodeModel::whereIn('id', $ids)->select();
            $data = NodeDetailModel::whereIn('node_id', $ids)->select();
            $previous = [];
            foreach ($product_node as $item) {
                $total = 0;
                foreach ($data as $v) {
                    if ($item->id == $v->node_id) {
                        $total += round((intval($v->factor * 100000) * intval($v->io_value * 10000)) / ($item->produce_amount * 10000 * 100000), 6);
                    }
                }
                $previous[$item->id]['pid'] = $item->pid;
                $previous[$item->id]['total'] = $total;
                $previous[$item->id]['is_factor'] = 0;
                $previous[$item->id]['path'] = $item->path;
                $previous[$item->id]['amount'] = $item->produce_amount;
            }

            // 因子节点
            $node_ids_of_factors = $node->factor_children_ids;
            $factor_data = NodeModel::whereIn('id', $node_ids_of_factors)->select();
            $sum_by_amount_ycl = 0;//原材料
            foreach ($factor_data as $v) {
                if (!isset($previous[$v->id])) {
                    $previous[$v->id]['pid'] = $v->pid;
                    $previous[$v->id]['total'] = round($v->factor_quotes * $v->factor, 6);
                    $previous[$v->id]['is_factor'] = 1;
                    $previous[$v->id]['path'] = $v->path;
                    $previous[$v->id]['amount'] = 1;
                } else {
                    $previous[$v->id]['toal'] += round($v->factor_quotes * $v->factor, 6);
                }

                //原材料
                if ($v->node_type == 2) {
                    $sum_by_amount_ycl += round($v->factor_quotes * $v->factor, 6);
                }
            }
            
            $list = [];
            foreach ($previous as $k1 => $v1) {
                $list[$k1]['x'] = $v1['total'];
                foreach ($previous as $v2) {
                    $pre_key = $v1['path'].$k1.'-';
                    if (stripos($v2['path'], $pre_key) !== false) {
                        $list[$k1]['x']  = (float)bcadd($list[$k1]['x'], $v2['total'], 6);
                    }
                }
            }

            $sum_by_amount = round($list[$node->id]['x'], 5);//总因子,每个
            $sum_by_amount_ycl = round($sum_by_amount_ycl, 5);//原材料因子,每个
            $sum_by_amount_cp = bcsub($sum_by_amount, $sum_by_amount_ycl, 5);//产品因子,每个

            $sum_by_quality = round($sum_by_amount * $node->produce_amount / $node->produce_quality, 5);//总因子,每kg
            $ycl_kg = round($sum_by_amount_ycl * $node->produce_amount / $node->produce_quality, 5);//原材料因子,每kg
            $cp_kg = bcsub($sum_by_quality, $ycl_kg, 5);//产品因子,每kg

            $extra = [
                'ycl' => (float)$sum_by_amount_ycl,
                'cp' => (float)$sum_by_amount_cp,
                'ycl_kg' => (float)$ycl_kg,
                'cp_kg' => (float)$cp_kg,
            ];

            //总排放量
            $carbon_result = round($sum_by_amount * $node->produce_amount, 2);

            //生成快照
            $children_node_ids = $node->children_ids;
            array_push($children_node_ids, $node->id);
            $tree = NodeModel::field('id,pid,name as topic,is_factor')->whereIn('id', $children_node_ids)->select()->toArray();
            $snapshot = $this->buildTree($tree, $node->pid);

            $result = Db::name('carbon_factor')->insert([
                'sn' => Random::alnum(14),
                'name' => $node->product->name . '-' . $node->name,
                'order_id' => $order->id,
                'user_id' => $node->user_id,
                'carbon_result' => $carbon_result,
                'carbon_factor_result' => $sum_by_amount,
                'carbon_factor_result_kg' => $sum_by_quality,
                'snapshot' => json_encode($snapshot, JSON_UNESCAPED_UNICODE),
                'createtime' => time(),
                'updatetime' => time(),
                'extra' => json_encode($extra, JSON_UNESCAPED_UNICODE),
                'nodes_carbon_factor' => json_encode($list)
            ]);

            // 修改订单核算状态
            $order->calculate_status = 1;
            $order->save();
        }

        echo '执行成功';
    }

    /**
     * 创建副本
     */
    public function copy()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'product_name|产品名称' => 'require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能创建');
        }

        if ($node->is_factor == 1) {
            $this->error('该节点是引用碳排放因子&数据库节点，不能创建');
        }

        Db::startTrans();
        try {
            // 添加产品
            $product = new ProductModel;
            $sn = Random::alnum(13);
            $product->name = $row['product_name'];
            $product->user_id = $this->auth->id;
            $product->sn = $sn;
            $product->company_id = $this->auth->company_id;
            $product->save();

            // 添加节点
            $list = [];
            $ids = $node->children_ids;
            array_push($ids, $node->id);
            $data = $this->model->whereIn('id', $ids)->select();
            foreach ($data as $k => $v) {
                $list[$k]['copy_id'] = $v->id;
                $list[$k]['level'] = $v->level - $node->level + 1;
                $list[$k]['user_id'] = $v->user_id;
                $list[$k]['name'] = $v->name;
                $list[$k]['product_id'] = $product->id;
                $list[$k]['is_factor'] = $v->is_factor;
                $list[$k]['factor_id'] = $v->factor_id;
                $list[$k]['factor_quotes'] = $v->factor_quotes;
                $list[$k]['is_template'] = $v->is_template;
                $list[$k]['template_id'] = $v->template_id;
                $list[$k]['produce_quality'] = $v->produce_quality;
                $list[$k]['produce_amount'] = $v->produce_amount;
                $list[$k]['node_type'] = $v->node_type;
                $list[$k]['copy_path'] = $v->path;
            }
            $new_data = $this->model->saveAll($list);

            foreach ($new_data as $v) {
                if ($v->level == 1) {
                    $v->pid = 0;
                    $v->path = '-';
                    $v->save();
                } else {
                    $arr = explode('-', $v->copy_path);
                    $copy_pid = $arr[count($arr) - 2];
                    $new_item = $this->model->where('copy_id', $copy_pid)->order('id', 'desc')->find();
                    $v->pid = $new_item->id;
                    $v->path = $new_item->path . $new_item->id . '-';
                    $v->save();
                }
            }

            // 添加节点详情
            $detail_list = [];
            $data = NodeDetailModel::whereIn('node_id', $ids)->select();
            foreach ($data as $k => $v) {
                $detail_list[$k]['user_id'] = $v->user_id;
                $detail_list[$k]['product_id'] = $product->id;
                $detail_list[$k]['io_type_id'] = $v->io_type_id;
                $detail_list[$k]['io_category_id'] = $v->io_category_id;
                $detail_list[$k]['type'] = $v->type;
                $detail_list[$k]['io_value'] = $v->io_value;
                $detail_list[$k]['copy_node_id'] = $v->node_id;
                $detail_list[$k]['copy_id'] = $v->id;
            }
            $nodeDetailModel = new NodeDetailModel;
            $new_data = $nodeDetailModel->saveAll($detail_list);

            foreach ($new_data as $v) {
                $new_item = $this->model->where('copy_id', $v->copy_node_id)->order('id', 'desc')->find();
                $v->node_id = $new_item->id;
                $v->save();
            }

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error('创建副本失败: ' . $e->getMessage());
        }

        $this->success('创建副本成功', $this->model);
    }

    /**
     * 提交订单
     */
    public function order()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能提交');
        }

        // 产品类型子节点
        $ids = $node->product_children_ids;

        array_push($ids, $row['node_id']);

        $data = NodeDetailModel::whereIn('node_id', $ids)->select();
        $factor_ids = $node->factor_children_ids;
        $total_type = count($data) + count($factor_ids);

        // 获取所有引用了模板的节点信息
        $template_nodes = $this->model->whereIn('id', $ids)->where('is_template', 1)->select();
        $item_template_id = []; //存取引用了的模板id
        foreach ($template_nodes as $v) {
            $item_template_id = array_merge($item_template_id, explode(',', $v->template_id));
        }
        if ($node->product->template_id != 0) {
            array_push($item_template_id, $node->product->template_id);
        }

        $item_template_id = array_unique($item_template_id);
        // 模板信息
        $template = Db::name('template')->field('id,user_id')->where('user_id', '<>', $this->auth->id)->whereIn('id', $item_template_id)->select();

        // 因子信息
        $factor_id = $this->request->post('factor_id', '');
        $factor_id = explode(',', $factor_id);
        $factor = Db::name('carbon_factor')->field('id,sn,name,price,user_id')->whereIn('id', $factor_id)->select();

        $total_energy = $this->get_service_energy($total_type);
        if ($factor) {
            foreach ($factor as $v) {
                $total_energy += $v['price'];
            }
        }

        Db::startTrans();
        try {
            // 提交订单
            $order_sn = generateOrderId('F');
            $order = OrderModel::create([
                'order_sn' => $order_sn,
                'node_id' => $node->id,
                'user_id' => $this->auth->id,
                'price' => $total_energy,
                'carbon_account_price' => $this->get_service_energy($total_type),
                'type' => 2,
                'factors' => json_encode($factor, JSON_UNESCAPED_UNICODE),
                'createtime' => time(),
                'updatetime' => time(),
                'company_id' => $this->auth->company_id,
            ]);

            // 订单因子数据
            $factor_arr = [];
            foreach ($factor as $k => $v) {
                $price = floor($v['price'] * 0.99);
                $platform_service_fee = $v['price'] - $price;
                $factor_arr[$k]['order_id'] = $order->id;
                $factor_arr[$k]['factor_id'] = $v['id'];
                $factor_arr[$k]['price'] = $price;
                $factor_arr[$k]['from_user'] = $v['user_id'];
                $factor_arr[$k]['user_id'] = $this->auth->id;
                $factor_arr[$k]['platform_service_fee'] = $platform_service_fee;
            }

            // 提交到订单因子表
            Db::name('order_factor')->insertAll($factor_arr);

            // 订单模板数据
            if (count($template) > 0) {
                $price = floor($this->get_service_energy($total_type) * 0.2 / count($template));
                $commission = floor($price * 0.99);
                $service_fee = $price - $commission;
                $template_arr = [];
                foreach ($template as $k => $v) {
                    $template_arr[$k]['order_id'] = $order->id;
                    $template_arr[$k]['template_id'] = $v['id'];
                    $template_arr[$k]['from_user'] = $v['user_id'];
                    $template_arr[$k]['user_id'] = $this->auth->id;
                    $template_arr[$k]['price'] = $price;
                    $template_arr[$k]['commission'] = $commission;
                    $template_arr[$k]['service_fee'] = $service_fee;
                }

                // 提交到订单模板表
                Db::name('order_template')->insertAll($template_arr);
            }

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error("提交失败: " . $e->getMessage());
        }
        $this->success('提交成功', ['order_sn' => $order_sn]);

    }

    /**
     * 引用模板
     */
    public function quote_template()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
            'template_sn|模板编号' => 'require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能引用模板');
        }

        if ($node->is_factor == 1) {
            $this->error('该节点是引用碳排放因子&数据库节点，不能引用模板');
        }

        $template = Db::name('template')->where('sn', $row['template_sn'])->find();
        if (!$template) {
            $this->error('当前模板不存在');
        }
        if ($template['user_id'] != $this->auth->id) {
            $order = Db::name('order')->where(['template_id' => $template['id'], 'user_id' => $this->auth->id, 'pay_state' => 1])->find();
            if (!$order) {
                $this->error('该模板不在我的模板库中');
            }
        }

        $new_node = [];
        Db::startTrans();
        try {
            //添加节点
            $list = [];
            $snapshot = json_decode($template['snapshot'], true);
            // 模板唯一标识
            $template_mark = Random::alnum(13);
            foreach ($snapshot as $k => $v) {
                $list[$k]['level'] = $v['level'] + $node->level;
                $list[$k]['user_id'] = $this->auth->id;
                $list[$k]['name'] = $v['topic'];
                $list[$k]['product_id'] = $node->product_id;
                $list[$k]['is_factor'] = $v['is_factor'];
                $list[$k]['factor_id'] = $v['factor_id'];
                $list[$k]['node_type'] = $v['node_type'];
                $list[$k]['origin_id'] = $v['id'];
                $list[$k]['origin_path'] = $v['path'];
                $list[$k]['origin_pid'] = $v['pid'];
                $list[$k]['from_template'] = $v['from_template'];
                $list[$k]['rank'] = $v['rank'] + $node->rank;
                $list[$k]['template_mark'] = $template_mark;
            }
            $new_data = $this->model->saveAll($list);

            foreach ($new_data as $v) {
                $reflect[$v->origin_id] = $v->id;
            }

            foreach ($new_data as $v) {
                if ($v->origin_path == '-') {
                    $v->pid = $node->id;
                    $v->path = $node->path . $node->id . '-';
                    $new_node = $v->toArray();
                } else {
                    $v->pid = $reflect[$v->origin_pid];
                    $v->path = $node->path . $node->id . $this->reflect($reflect, $v->origin_path);
                }
                $v->save();
            }

            //添加节点输入输出类型类别
            $detail_list = [];
            $node_detail = json_decode($template['node_detail'], true);
            foreach ($node_detail as $k => $v) {
                $detail_list[$k]['user_id'] = $this->auth->id;
                $detail_list[$k]['product_id'] = $node->product_id;
                $detail_list[$k]['io_type_id'] = $v['io_type_id'];
                $detail_list[$k]['io_category_id'] = $v['io_category_id'];
                $detail_list[$k]['type'] = $v['type'];
                $detail_list[$k]['io_value'] = NULL;
                $detail_list[$k]['copy_node_id'] = $v['node_id'];
                $detail_list[$k]['copy_id'] = $v['id'];
            }

            $nodeDetailModel = new NodeDetailModel;
            $new_data = $nodeDetailModel->saveAll($detail_list);

            foreach ($new_data as $v) {
                $new_item = $this->model->where('origin_id', $v->copy_node_id)->order('id', 'desc')->find();
                $v->node_id = $new_item->id;
                $v->save();
            }

            //修改当前节点信息
            if ($node->template_id) {
                $template_id = explode(',', $node->template_id);
                array_push($template_id, $template['id']);
                $template_id = implode(',', $template_id);
            } else {
                $template_id = $template['id'];
            }
            $node->is_template = 1;
            $node->template_id = $template_id;
            $node->save();

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error('引用模板失败: ' . $e->getMessage());
        }

        $this->success('引用模板成功', ['node_id' => $new_node['id'] ?? 0]);
    }

    protected function reflect($reflect, $path)
    {
        $item = [];
        $arr = explode('-', $path);
        foreach ($arr as $v) {
            if ($v) {
                $item[] = $reflect[$v];
            } else {
                $item[] = $v;
            }
        }
        return implode('-', $item);
    }

    /**
     * 查看核算结果
     */
    public function check_calculate_result()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'order_sn|订单编号' => 'require'
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $order = OrderModel::where('order_sn', $row['order_sn'])->where('type', 2)->find();

        if (!$order) {
            $this->error('订单不存在');
        }

        $data = Db::name('carbon_factor')->field('id,sn')->where('order_id', $order->id)->find();

        if (!$data) {
            $this->error('核算中，请稍等');
        }
            
        $this->success('核算成功', $data);
    }

    public function check_template()
    {
        if (!$this->request->isPost()) {
            $this->error('请求错误');
        }

        //接收并验证数据
        $row = $this->request->post('', '', 'trim,xss_clean');

        $rule = [
            'node_id|节点ID' => 'number|require',
        ];
        $validate = $this->validate($row, $rule);
        if ($validate !== true) {
            $this->error($validate);
        }

        $node = $this->model->where('id', $row['node_id'])->find();

        if (!$node) {
            $this->error('节点不存在');
        }

        if ($node->user_id != $this->auth->id) {
            $this->error('你不是节点拥有者，不能查看');
        }

        if (!$node->template_mark && $node->origin_path == '-') {
            $this->error('非模板节点，不能查看');
        }

        $ids = $this->model->where('product_id', $node->product_id)
            ->where('path', 'like', $node->path.$node->id.'-%')->column('id');
        array_push($ids, $node->id);

        $data = Db::name('node_detail')
            ->alias('a')
            ->join('io_category b', 'b.id = a.io_category_id')
            ->distinct(true)
            ->field('b.name,b.type')
            ->whereIn('a.node_id', $ids)
            ->select();

        $energy = [];
        $waste = [];
        foreach ($data as $v) {
            if ($v['type'] == 0) {
                $energy[] = $v['name'];
            } else {
                $waste[] = $v['name'];
            }
        }

        $tree = NodeModel::field('convert(id,char) id,convert(pid,char) pid,name as topic,convert(is_factor,char) is_factor,template_mark,`rank`,origin_pid')
            ->where('product_id', $node->product_id)
            ->where(function($query) use ($node) {
                $query->where('template_mark', $node->template_mark);
                $query->whereOr(function($query1) use ($node) {
                    $query1->where('rank', $node->rank + 1);
                    $query1->where('origin_path', '-');
                    $query1->where('path', 'like', $node->path.$node->id.'-%');
                });
            })
            ->select()->toArray();

        $tree = $this->buildTree($tree, $node->pid);

        $this->success('ok', ['node_tree' => $tree, 'energy' => $energy, 'waste' => $waste]);
    }

}
